﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Windows.Markup;
using System.ComponentModel;

namespace Vision.Core.ActivityComponents.Assembly
{
    [ContentProperty("Body")]
    [Designer(typeof(InvokeMethodDesigner))]
    public class InvokeMethod : NativeActivity
    {
        /// <summary>
        /// 
        /// </summary>
        [Category("Input")]
        [DefaultValue(null)]
        [RequiredArgument]
        public InArgument<string> MethodName { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Category("Input")]
        [DefaultValue(null)]
        public InArgument<object[]> MethodArguments { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Browsable(false)]
        [DefaultValue(null)]
        public ActivityAction Body { get; set; }

        public InvokeMethod()
        {
            this.Body = new ActivityAction();
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void Execute(NativeActivityContext context)
        {
            object instance = context.Properties.Find("1ec83ea-51f8-4891-87c2-16638f870c3a");
            if (instance != null)
            {
                Type instanceType = instance.GetType();

                System.Reflection.MethodInfo method = instanceType.GetMethod(this.MethodName.Get(context));
                if (method != null)
                    method.Invoke(instance, this.MethodArguments.Get(context));

                //instanceType.InvokeMember(this.MethodName.Get(context), System.Reflection.BindingFlags.InvokeMethod, null, instance, this.MethodArguments.Get(context));
            }

            if (this.Body != null)
                context.ScheduleAction(this.Body);
        }
    }

    [Designer(typeof(InvokeMethodReturnDesigner))]
    public class InvokeMethod<T> : InvokeMethod
    {
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false)]
        [DefaultValue(null)]
        public new ActivityAction<T> Body { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Category("Output")]
        [DefaultValue(null)]
        public OutArgument<T> ReturnValue { get; set; }

        public InvokeMethod()
        {
            this.Body = new ActivityAction<T>()
            {
                Argument = new DelegateInArgument<T>()
                {
                    Name = "returnValue"
                }
            };
        }

        protected override void Execute(NativeActivityContext context)
        {
            T return_value = default(T);

            object instance = context.Properties.Find("1ec83ea-51f8-4891-87c2-16638f870c3a");
            if (instance != null)
            {
                Type instanceType = instance.GetType();

                System.Reflection.MethodInfo method = instanceType.GetMethod(this.MethodName.Get(context));
                if (method != null)
                    return_value = (T)method.Invoke(instance, this.MethodArguments.Get(context));
            }

            this.ReturnValue.Set(context, return_value);

            if (this.Body != null)
                context.ScheduleAction<T>(this.Body, return_value);
        }
    }
}
